package client;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import javax.jmdns.JmDNS;
import javax.jmdns.ServiceEvent;
import javax.jmdns.ServiceListener;
import java.net.Socket;
import java.rmi.*;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;


import ClientTests.RMIServer;

/*
 * Author: David Swords
 * Email: davidswordster@gmail.com
 * Skype: masterexploder1985
 * 
 * The implementation of the client class used for various devices.
 */

public class ClientImpl
{
	private int PORT;
	private String HOST,NAME,HS;
	private boolean HAND_SHAKING;
	public RMIServer SERVER;
	private Registry REGISTRY;
	
	public ClientImpl() throws IOException{
		HAND_SHAKING = false;
		HS = "";
	}
	
	public void connectToService(String serviceType) throws IOException, InterruptedException{
		final JmDNS jmdns = JmDNS.create();
		if(HAND_SHAKING)System.out.println("created JmDNS.\n");
		jmdns.addServiceListener(serviceType, new Listener());
		if(HAND_SHAKING)System.out.println("Listener added.\n");
		RMISetup();
	}
	
	public void setHandshaking(boolean b){
		HAND_SHAKING = b;
	}
	
	public String handShake(){
		return HS;
	}
	
	private void RMISetup() throws InterruptedException{
	 	if(isConnected()){
			System.setSecurityManager(new RMISecurityManager());
			try{	
				if(HAND_SHAKING)System.out.println("Security Manager loaded\n");
			  	String url = "SAMPLE-SERVER";
			  	REGISTRY = LocateRegistry.getRegistry(HOST);
			  	RMIServer remoteObject = (RMIServer)REGISTRY.lookup(url);
			  	if(HAND_SHAKING)System.out.println("Remote Object Received"+"\n");
			 	SERVER = remoteObject;
			}
			catch (RemoteException exc){
				if(HAND_SHAKING)System.out.println("Error in lookup: " + exc.toString()+"\n");
			  	System.exit(0);
			}
			catch (java.rmi.NotBoundException exc){
				if(HAND_SHAKING)System.out.println("NotBound: " + exc.toString()+"\n");
			  	System.exit(0);
			}
	 	}
	 	else{
	 		if(HAND_SHAKING)System.out.println("Connection attempt to RMIServer on host:"+HOST+" and on port: "+PORT+"has failed\n");
	 		System.exit(0);
	 	}
	}
	
	public boolean isConnected() throws InterruptedException{
		try{
			Thread.sleep((long)10000);
		 	Socket toServer = new Socket(HOST, PORT);
			PrintWriter out = new PrintWriter(toServer.getOutputStream(), true);
		 	out.println("CLIENT");
		 	if(HAND_SHAKING)System.out.println("Shout sent to host: "+HOST+" on port: "+PORT+"\n");
			BufferedReader in = new BufferedReader(new InputStreamReader(toServer.getInputStream()));
			String msg = in.readLine();
			if(msg.equals("SERVER")){
				if(HAND_SHAKING)System.out.println("Echo from host: "+HOST+" on port: "+PORT+" has been heard.\n");
				out.close();
			 	toServer.close();
				return true;
			}
			else{
				if(HAND_SHAKING)System.out.println("Connection failed: "+msg+" was received.\n");
				out.close();
			 	toServer.close();
				return false;
			}
      	}
		catch (IOException ioe){
			if(HAND_SHAKING)System.out.println(ioe.toString()+"\n");
    	 	return false;
      	}
		catch (SecurityException se){
			if(HAND_SHAKING)System.out.println(se.toString()+"\n");
     		return false;
      	}
	}
	
	private class Listener implements ServiceListener{	
		public void serviceAdded(final ServiceEvent event){
			if(HAND_SHAKING)System.out.println("Service added. Name: "+event.getName()+" Type: "+event.getType()+"\n");
			event.getDNS().requestServiceInfo(event.getType(), event.getName(), 0);
		}

		public void serviceRemoved(ServiceEvent event){
			if(HAND_SHAKING)System.out.println("Service removed. Name: "+event.getName()+" Type: "+event.getType()+"\n");
		}

		public void serviceResolved(ServiceEvent event){
			HOST = event.getInfo().getHostAddress();
			NAME = event.getInfo().getName();
			PORT = event.getInfo().getPort();
			if(HAND_SHAKING)System.out.println("Service resolved. Name: "+NAME+" Host: "+HOST+" Port: "+PORT+"\n");
		}
	}
}
